package xj.graph2d;

import static xj.util.xml.XMLUtil.getXMLAttributeString;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import xj.lang.CodeWriter;

public abstract class LabelBase extends DrawShapeBase implements Label {

  @Override
  public void copyTo(DrawShapeBase s) 
    throws CloneNotSupportedException {
    super.copyTo(s);
    if (s instanceof LabelBase) {
      LabelBase l = (LabelBase) s;
      if (offset != null) {
	l.offset = new Offset(offset);
      } else {
	l.offset = null;
      }
      l.islabel_ = islabel_;
    }
  }

  public Offset getOffset() {
    return offset;
  }

  public void setOffset(Offset offset) {
    this.offset = offset;
  }

  public void setOffset(float dx, float dy) {
    if (offset != null) {
      offset.set(dx, dy);
    } else {
      offset = new Offset(dx, dy);
    }
  }

  public void adjustOffset(float dx, float dy) {
    if (offset != null) {
      offset.dx += dx;
      offset.dy += dy;
    } else {
      offset = new Offset(dx, dy);
    }
  }

  public boolean isLabel() {
    return islabel_;
  }

  public void isLabel(boolean b) {
    islabel_ = b;
  }

  public void addLabelListener(LabelListener listener) {
    if (listener != null) {
      labelListeners.add(listener);
    }
  }

  public void removeLabelListener(LabelListener listener) {
    if (listener != null) {
      labelListeners.remove(listener);
    }
  }

  public void fireLabelChanged() {
    if (debug) System.out.println("LabelBase.fireLabelChanged()");

    Iterator<LabelListener> iter = labelListeners.iterator();
    while (iter.hasNext()) {
      Object o = iter.next();
      if (o instanceof LabelListener) {
	((LabelListener) o).labelChanged(this);
      }
    }

    DrawShape parent = getParent();
    if (parent instanceof Label) {
      ((Label) parent).fireLabelChanged();
    } else if (parent instanceof GraphNodeBase) {
      LabelListener pll = ((GraphNodeBase) parent).getLabelListener();
      if (pll != null) {
	pll.labelChanged(this);
      }
    }
  }

  @Override
  protected Map<String, Object> getXMLAttributes() {
    Map<String, Object> attrs = super.getXMLAttributes();
    if (attrs == null) {
      attrs = new HashMap<String, Object>();
    }
    attrs.put("label", islabel_);
    return attrs;
  }

  @Override
  protected void writeXMLElements(CodeWriter out, int mode,
				  String namespacePrefix) {
    if (out != null) {
      super.writeXMLElements(out, mode, namespacePrefix);

      if (offset != null) {
	String nodename = getPrefixedName("Offset", namespacePrefix);
	out.println("<" + nodename + ' '  + 
		    getXMLAttributeString("dx", offset.dx) + ' ' + 
		    getXMLAttributeString("dy", offset.dy) + "/>");
      }
    }
  }

  @Override
  protected void processXMLAttributes(org.w3c.dom.Element node) {
    if (node != null) {
      super.processXMLAttributes(node);

      String bs = node.getAttribute("label");
      try {
	islabel_ = Boolean.valueOf(bs);
      } catch (NumberFormatException ex) {
      }
    }
  }

  @Override
  protected void processXMLElement(org.w3c.dom.Element e, String namespaceURI) {
    if (e != null) {
      if ("Offset".equals(e.getLocalName())) {
	String dxs, dys;
	dxs = e.getAttribute("dx");
	dys = e.getAttribute("dy");
	float dx = 0, dy = 0;
	try {
	  dx = Float.parseFloat(dxs);
	  dy = Float.parseFloat(dys);
	  if (offset == null) {
	    offset = new Offset(dx, dy);
	  } else {
	    offset.set(dx, dy);
	  }
	} catch (NumberFormatException ex) {
	}
      } else {
	super.processXMLElement(e, namespaceURI);
      }
    }
  }

  protected Offset offset;

  protected boolean islabel_ = true;

  protected List<LabelListener> labelListeners = new ArrayList<LabelListener>();

}
